package cn.pangza.user.config;

import cn.pangza.common.utils.ResponseData;
import cn.pangza.user.filter.JwtFilter;
import cn.pangza.user.service.SecurityService;
import cn.pangza.user.service.SecurityUserService;
import cn.pangza.user.service.impl.SecurityServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    @Autowired
    SecurityUserService userService;

    @Autowired
    JwtFilter jwtFilter;

    @Autowired
    ObjectMapper objectMapper;

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userService);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        return new ProviderManager(daoAuthenticationProvider);
    }

    @Bean("ss")
    SecurityService securityService() {
        return new SecurityServiceImpl();
    }


    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .authorizeHttpRequests(auth -> {
                    auth
                            .requestMatchers(new AntPathRequestMatcher("/api/login")).permitAll()
                            .requestMatchers(new AntPathRequestMatcher("/api/**/pub/**")).permitAll()
                            .anyRequest().authenticated();
                })
                .exceptionHandling(e ->
                        e.authenticationEntryPoint((request, response, exception) -> {
                            System.out.println("request.getRequestURI() = " + request.getRequestURI());
                            if (exception instanceof BadCredentialsException) {
                                System.out.println("用户名或者密码输入错误，登录失败");
                            } else if (exception instanceof DisabledException) {
                                System.out.println("账户被禁用，登录失败");
                            } else if (exception instanceof LockedException) {
                                System.out.println("账户被锁定，登录失败");
                            } else if (exception instanceof AccountExpiredException) {
                                System.out.println("账户过期，登录失败");
                            } else if (exception instanceof CredentialsExpiredException) {
                                System.out.println("密码过期，登录失败");
                            } else {
                                System.out.println("hello" + exception.getClass().toString());
                            }
                            // 认证异常
                            response.setContentType("application/json;charset=utf-8");
                            response.getWriter().write(objectMapper.writeValueAsString(ResponseData.error("用户名或密码输入错误")));
                        }).accessDeniedHandler((request, response, exception) -> {
                            // 授权异常
                            response.setContentType("application/json;charset=utf-8");
                            response.getWriter().write(objectMapper.writeValueAsString(ResponseData.permissionError(null)));
                        })
                )
                .addFilterAfter(jwtFilter, UsernamePasswordAuthenticationFilter.class)
                .httpBasic()
                .and()
                .csrf(c -> c.disable());
        return httpSecurity.build();
    }
}
